package com.niiwoo.civet.mobile.controller.creditor;

import com.alibaba.dubbo.config.annotation.Reference;
import com.niiwoo.civet.account.service.AccountDubboService;
import com.niiwoo.civet.mobile.vo.common.ConfigItem;
import com.niiwoo.civet.mobile.vo.common.ConfigVO;
import com.niiwoo.civet.mobile.vo.common.CreditorSalePageVO;
import com.niiwoo.civet.mobile.vo.request.creditor.*;
import com.niiwoo.civet.mobile.vo.response.creditor.*;
import com.niiwoo.civet.mobile.vo.response.invest.SoldOutGuidanceResponseVO;
import com.niiwoo.civet.trade.constant.TradeRedisKey;
import com.niiwoo.civet.trade.dto.common.FilterInvestConfigDTO;
import com.niiwoo.civet.trade.dto.request.creditor.CreditorAgreementUrlRequestDTO;
import com.niiwoo.civet.trade.dto.request.creditor.CreditorSalePageRequestDTO;
import com.niiwoo.civet.trade.dto.request.creditor.TradableInvestOrderFilterRequestDTO;
import com.niiwoo.civet.trade.dto.response.InvestFlowConfigResponseDTO;
import com.niiwoo.civet.trade.dto.response.RelationInvestStdConfigItemDTO;
import com.niiwoo.civet.trade.dto.response.creditor.CreditorAgreementUrlResponseDTO;
import com.niiwoo.civet.trade.dto.response.creditor.CreditorSaleDetailResponseDTO;
import com.niiwoo.civet.trade.dto.response.creditor.CreditorSalePageResponseDTO;
import com.niiwoo.civet.trade.dto.response.creditor.TradableInvestOrderStatDTO;
import com.niiwoo.civet.trade.enums.InvestStdProductTypeEnum;
import com.niiwoo.civet.trade.service.creditor.CreditorConfigDubboService;
import com.niiwoo.civet.trade.service.creditor.CreditorRightsDubboService;
import com.niiwoo.civet.trade.service.invest.InvestDubboService;
import com.niiwoo.tripod.provider.exception.BizException;
import com.niiwoo.tripod.web.annotation.AuthIgnore;
import com.niiwoo.tripod.web.component.AccessRateLimiter;
import com.niiwoo.tripod.web.util.PrincipalContext;
import com.niiwoo.tripod.web.vo.Empty;
import com.niiwoo.tripod.web.vo.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import jodd.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.FastDateFormat;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * Created by zhangwanli on 2018/5/12.
 */
@Slf4j
@RestController
@RequestMapping("/creditorRights")
@Api(tags = "债权", description = "/creditorRights")
public class CreditorRightsController {

    @Autowired
    private AccessRateLimiter accessRateLimiter;

    @Reference(version = "1.0.0")
    private CreditorRightsDubboService creditorRightsDubboService;

    @Reference(version = "1.0.0")
    private AccountDubboService accountDubboService;

    @Reference(version = "1.0.0")
    private InvestDubboService investDubboService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Value("${online_time_for_creditor}")
    private String onlineTime;

    @PostMapping("/cancelTransferApply")
    @ApiOperation("取消债转申请")
    public Empty cancelTransferApply(@RequestBody @Valid CreditorRightsIdsRequestVO request) {
        //TODO zwl
        return Empty.getInstance();
    }

    /*@PostMapping("/creditorSaleSelector")
    @ApiOperation("债转标的列表——筛选信息(xiewen)")
    @AuthIgnore
    public Result<List<Object>> queryCreditorSaleSelector() {

        List<Object> requestDto = new ArrayList<>();
        List<FilterInvestConfigDTO> responseDTO = creditorRightsDubboService.queryCreditorSaleSelector();


        if (responseDTO != null) {
            requestDto.addAll(responseDTO);
        }

        return Result.with(requestDto);
    }*/

    @PostMapping("/queryCreditorIsInvest")
    @ApiOperation("债转标的列表——红点显示 是否有可投资的债转标(xiewen)")
    @AuthIgnore
    public Result<IsCreditorNumResponseVO> queryCreditorIsInvest() {

        IsCreditorNumResponseVO responseDTO = new IsCreditorNumResponseVO();
        Integer num = creditorRightsDubboService.queryCreditorIsInvest();
        responseDTO.setNum(num);
        return Result.with(responseDTO);
    }

    @PostMapping("/creditorSalePage")
    @ApiOperation("债转标的列表——分页列表(xiewen)")
    @AuthIgnore
    public Result<CreditorSalePageResponseVO> getCreditorSalePage(@RequestBody @Valid CreditorSalePageRequestVO requestVO) {
        String userId = PrincipalContext.getUserId();
        if (userId != null) {
            boolean limit = accessRateLimiter.userLimit(userId, "creditor-sale-page", 1, AccessRateLimiter.Unit.SECOND, 10);
            if (limit) {
                throw new BizException("SYS1001");  //亲爱的用户，您操作频率过快，请稍后再试
            }
        }

        CreditorSalePageRequestDTO requestDTO = new CreditorSalePageRequestDTO();
        requestDTO.setOffset((requestVO.getPageNumber() - 1) * requestVO.getPageSize());
        requestDTO.setPageSize(requestVO.getPageSize());
        requestDTO.setSort(requestVO.getSort());
        requestDTO.setSortType(requestVO.getSortType());

        FilterInvestConfigDTO.Config periodConfigure = requestVO.getPeriodType();
        if (Objects.nonNull(periodConfigure)) {
            CreditorSalePageRequestDTO.PeriodCondition periodCondition = transferCondition(periodConfigure);
            requestDTO.setPeriodCondition(periodCondition);
        }

        FilterInvestConfigDTO.Config rateConfigure = requestVO.getRateType();
        if (Objects.nonNull(rateConfigure)) {
            CreditorSalePageRequestDTO.RateCondition rateCondition = transferRateCondition(rateConfigure);
            requestDTO.setRateCondition(rateCondition);
        }

        FilterInvestConfigDTO.Config investableConfigure = requestVO.getInvestableType();
        if(Objects.nonNull(investableConfigure)){
            CreditorSalePageRequestDTO.InvestableType investableType = transferInvestableCondition(investableConfigure);
            requestDTO.setInvestableType(investableType);
        }
        requestDTO.setRepaymentType(requestVO.getRepaymentType());
        requestDTO.setFavorableType(requestVO.getFavorableType());
        requestDTO.setProductType(requestVO.getProductType());

        List<CreditorSalePageResponseDTO> responseDTOs = creditorRightsDubboService.getCreditorSalePage(requestDTO);

        CreditorSalePageResponseVO responseVO = new CreditorSalePageResponseVO();
        if (!CollectionUtils.isEmpty(responseDTOs)) {
            for (CreditorSalePageResponseDTO responseDTO : responseDTOs) {
                CreditorSalePageVO creditorSalePageVO = new CreditorSalePageVO();
                BeanUtils.copyProperties(responseDTO, creditorSalePageVO);
                responseVO.getItems().add(creditorSalePageVO);
            }
        }
        boolean isSoldOut = true;// 已售罄
        for (CreditorSalePageResponseDTO dto : responseDTOs) {
            if (requestVO.getPageNumber() == 1) {// 第一页
                if (dto.getStatus() == 1) {
                    isSoldOut = false;
                }
            }
        }
        if (requestVO.getPageNumber() == 1) {// 第一页
            responseVO.setIsSoldOut(isSoldOut ? Byte.valueOf("1") : Byte.valueOf("0"));
            if (isSoldOut) {// 已售罄
                responseVO.setSoldOutGuidanceResponseVO(this.getSoldOutGuidanceResponseVO(userId));
            }
        }
        return Result.with(responseVO);
    }

    private SoldOutGuidanceResponseVO getSoldOutGuidanceResponseVO(String userId) {
        InvestFlowConfigResponseDTO responseDTO = investDubboService.getSoldOutGuidanceTransfer(userId);
        if (responseDTO != null) {
            SoldOutGuidanceResponseVO soldOutGuidanceResponseVO = new SoldOutGuidanceResponseVO();
            soldOutGuidanceResponseVO.setType(responseDTO.getType().getValue());
            soldOutGuidanceResponseVO.setContent(responseDTO.getContent());
            soldOutGuidanceResponseVO.setButtonText(responseDTO.getButtonText());
            soldOutGuidanceResponseVO.setLink(responseDTO.getLink());
            soldOutGuidanceResponseVO.setIsShow(responseDTO.getIsShow());
            soldOutGuidanceResponseVO.setTitle(responseDTO.getTitle());
            return soldOutGuidanceResponseVO;
        }
        return null;
    }

    public CreditorSalePageRequestDTO.InvestableType transferInvestableCondition(FilterInvestConfigDTO.Config investableConfigure) {
        CreditorSalePageRequestDTO.InvestableType rateCondition = new CreditorSalePageRequestDTO().new InvestableType();
        rateCondition.setBegin(new BigDecimal(investableConfigure.getMinval().toString()));
        rateCondition.setBeginQueryType(Byte.parseByte(investableConfigure.getMinvalCalSymbol().toString()));
        rateCondition.setEnd(investableConfigure.getMaxval() != null ? new BigDecimal(investableConfigure.getMaxval().toString()) : null);
        rateCondition.setEndQueryType(investableConfigure.getMaxvalCalSymbol() != null ? Byte.parseByte(investableConfigure.getMaxvalCalSymbol().toString()) : null);
        return rateCondition;
    }

    public CreditorSalePageRequestDTO.PeriodCondition transferCondition(
            FilterInvestConfigDTO.Config periodConfigure) {
        CreditorSalePageRequestDTO.PeriodCondition periodCondition = new CreditorSalePageRequestDTO().new PeriodCondition();
        periodCondition.setBegin(periodConfigure.getMinval().intValue());
        periodCondition.setUnit(Byte.parseByte(periodConfigure.getTermUnit().toString()));
        periodCondition.setEndQueryType(periodConfigure.getMaxvalCalSymbol() != null ? Byte.parseByte(periodConfigure.getMaxvalCalSymbol().toString()) : null);
        periodCondition.setEnd(periodConfigure.getMaxval() != null ? new BigDecimal(periodConfigure.getMaxval().toString()).intValue() : null);
        periodCondition.setBeginQueryType(Byte.parseByte(periodConfigure.getMinvalCalSymbol().toString()));
        return periodCondition;
    }

    public CreditorSalePageRequestDTO.RateCondition transferRateCondition(
            FilterInvestConfigDTO.Config rateConfigure) {
        BigDecimal hunderd = BigDecimal.valueOf(100);
        CreditorSalePageRequestDTO.RateCondition rateCondition = new CreditorSalePageRequestDTO().new RateCondition();
        rateCondition.setBegin(new BigDecimal(rateConfigure.getMinval().toString()).divide(hunderd).setScale(2,BigDecimal.ROUND_DOWN));
        rateCondition.setBeginQueryType(Byte.parseByte(rateConfigure.getMinvalCalSymbol().toString()));
        rateCondition.setEnd(rateConfigure.getMaxval() != null ? new BigDecimal(rateConfigure.getMaxval().toString()).divide(hunderd).setScale(2,BigDecimal.ROUND_DOWN) : null);
        rateCondition.setEndQueryType(rateConfigure.getMaxvalCalSymbol() != null ? Byte.parseByte(rateConfigure.getMaxvalCalSymbol().toString()) : null);
        return rateCondition;
    }

    @PostMapping("/creditorSaleDetail")
    @ApiOperation("债转标的详情(xiewen)")
    @AuthIgnore
    public Result<CreditorSaleDetailResponseVO> getCreditorSaleDetail(@RequestBody @Valid CreditorSaleDetailRequestVO requestVO) {

        CreditorSaleDetailResponseDTO responseDTO = creditorRightsDubboService.getCreditorSaleDetail(requestVO.getCreditorSaleDetailId(), requestVO.getSaleUserId());

        CreditorSaleDetailResponseVO creditorSaleDetailResponseVO = new CreditorSaleDetailResponseVO();
        if (responseDTO != null) {
            BeanUtils.copyProperties(responseDTO, creditorSaleDetailResponseVO);
            String protocolNumber = "ZQ" + FastDateFormat.getInstance("yyMMdd").format(new Date()) + creditorSaleDetailResponseVO.getCreditorSaleDetailId();
            creditorSaleDetailResponseVO.setProtocolNumber(protocolNumber);
            creditorSaleDetailResponseVO.setCreditorAgreementUrl(responseDTO.getCreditorAgreementUrl() + responseDTO.getCreditorUserId());
            creditorSaleDetailResponseVO.setCreditorRiskAgreementUrl(responseDTO.getCreditorRiskAgreementUrl() + responseDTO.getCreditorUserId());
        }
        creditorSaleDetailResponseVO.setAssigneeInterest(responseDTO.getSaleAmount().subtract(responseDTO.getAmount()).add(responseDTO.getOffAmount()));
        return Result.with(creditorSaleDetailResponseVO);
    }

    @PostMapping("/myInvestNewFlag")
    @ApiOperation("我的投资New标识(xiewen)")
    public Result<MyInvestNewResponseVO> myInvestNew() {
        String userId = PrincipalContext.getUserId();

        if (StringUtil.isBlank(userId)) {
            throw new BizException("USR10019");
        }

        MyInvestNewResponseVO isFirstClickResponseVO = new MyInvestNewResponseVO();

        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date;
        Date currentDate = new Date();
        try {
            date = format.parse(onlineTime);
        } catch (ParseException e) {
            log.info("myInvestNewFlag时间转换异常");
            return Result.with(isFirstClickResponseVO);
        }

        if (currentDate.before(new DateTime(date).plusMonths(1).toDate())) {
            String userIsFirstClickKey = TradeRedisKey.INVEST_FRIST_CLICK_SHOW + userId;
            if (!redisTemplate.hasKey(userIsFirstClickKey)) {
                isFirstClickResponseVO.setShowRedPoint((byte) 1);
            }
        }

        return Result.with(isFirstClickResponseVO);
    }

    @PostMapping("/clickInvestNewFlag")
    @ApiOperation("我的投资点击New标识时触发(xiewen)")
    public Result<Empty> clickInvestNewFlag() {
        String userId = PrincipalContext.getUserId();

        if (StringUtil.isBlank(userId)) {
            throw new BizException("USR10019");
        }
        MyInvestNewResponseVO isFirstClickResponseVO = new MyInvestNewResponseVO();

        String userIsFirstClickKey = TradeRedisKey.INVEST_FRIST_CLICK_SHOW + userId;

        redisTemplate.opsForValue().set(userIsFirstClickKey, String.valueOf(isFirstClickResponseVO.getShowRedPoint()),30, TimeUnit.DAYS);

        return Result.with(Empty.getInstance());
    }

    @PostMapping("/IsShowFunctionPage")
    @ApiOperation("点击债权转让后时候显示新功能介绍页面(xiewen)")
    public Result<IsFirstClickResponseVO> IsShowFunctionPage() {
        String userId = PrincipalContext.getUserId();

        if (StringUtil.isBlank(userId)) {
            throw new BizException("USR10019");
        }

        IsFirstClickResponseVO isFirstClickResponseVO = new IsFirstClickResponseVO();

        String userIsFirstClickKey = TradeRedisKey.FUNCTION_PAGE_IS_SHOW;

        DateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date date;
        Date currentDate = new Date();
        try {
            date = format.parse(onlineTime);
        } catch (ParseException e) {
            log.info("IsShowFunctionPage时间转换异常");
            return Result.with(isFirstClickResponseVO);
        }
        if (currentDate.before(new DateTime(date).plusMonths(1).toDate())) {
            if (!redisTemplate.opsForSet().isMember(userIsFirstClickKey,userId)) {
                isFirstClickResponseVO.setIsFirstClick((byte) 0);
            }
        }
        TradableInvestOrderStatDTO creditorSaleOrderRateAreaDTO = creditorRightsDubboService.getCreditorSaleOrderRateArea();
        isFirstClickResponseVO.setMinFeeRate(creditorSaleOrderRateAreaDTO.getMinFeeRate());
        return Result.with(isFirstClickResponseVO);
    }

    @PostMapping("/experience")
    @ApiOperation("新功能介绍页面点击立即体验时触发(xiewen)")
    public Result<Empty> Experience() {
        String userId = PrincipalContext.getUserId();

        if (StringUtil.isBlank(userId)) {
            throw new BizException("USR10019");
        }

        String userIsShowPagekKey = TradeRedisKey.FUNCTION_PAGE_IS_SHOW;

        redisTemplate.opsForSet().add(userIsShowPagekKey, userId);

        return Result.with(Empty.getInstance());
    }

    @PostMapping("/transferableCreditWindow")
    @ApiOperation("可转让债权的条件弹窗(黄敏)")
    public Result<TransferableCreditWindowResponseVO> transferableCreditWindow() {
        String userId = PrincipalContext.getUserId();

        if (StringUtil.isBlank(userId)) {
            throw new BizException("USR10019");
        }

        // 是否显示弹窗：0不显示弹窗  1显示弹窗
        TransferableCreditWindowResponseVO responseVO = new TransferableCreditWindowResponseVO();
        responseVO.setIsShowWindow(Byte.valueOf("1"));
        String userIsWindowClickKey = TradeRedisKey.TRANSFERABLE_CREDIT_WINDOW;
        if (redisTemplate.opsForSet().isMember(userIsWindowClickKey,userId)) {
            responseVO.setIsShowWindow(Byte.valueOf("0"));
        }

        return Result.with(responseVO);
    }

    @PostMapping("/recordTransferableCreditWindow")
    @ApiOperation("记录用户是否已弹过可转让债权的条件弹窗(黄敏)")
    public Empty recordTransferableCreditWindow() {
        String userId = PrincipalContext.getUserId();

        if (StringUtil.isBlank(userId)) {
            throw new BizException("USR10019");
        }

        TransferableCreditWindowResponseVO responseVO = new TransferableCreditWindowResponseVO();
        responseVO.setIsShowWindow(Byte.valueOf("0"));
        String userIsWindowClickKey = TradeRedisKey.TRANSFERABLE_CREDIT_WINDOW;
        redisTemplate.opsForSet().add(userIsWindowClickKey, userId);

        return Empty.getInstance();
    }

    @PostMapping("/creditorAgreementUrl")
    @ApiOperation("债权服务协议相关路径")
    public Result<List<CreditorAgreementUrlResponseVO>> creditorAgreementUrl(@RequestBody @Valid CreditorAgreementUrlRequestVO requestVO){
        List<CreditorAgreementUrlResponseVO> responseVO = new ArrayList<>();
        CreditorAgreementUrlRequestDTO dto = new CreditorAgreementUrlRequestDTO();
        dto.setIsBatch(requestVO.getIsBatch());
        dto.setProjectInvestId(requestVO.getProjectInvestId());
        dto.setSaleAmount(requestVO.getSaleAmount());
        List<CreditorAgreementUrlResponseDTO> list = creditorRightsDubboService.queryCreditorAgreementUrl(dto);
        if(!CollectionUtils.isEmpty(list)){
            for(CreditorAgreementUrlResponseDTO responseDTO : list){
                CreditorAgreementUrlResponseVO response = new CreditorAgreementUrlResponseVO();
                response.setLink(responseDTO.getLink());
                response.setTitle(responseDTO.getTitle());
                responseVO.add(response);
            }
        }
        return Result.with(responseVO);

    }
    @Reference(version = "1.0.0")
    private CreditorConfigDubboService creditorConfigDubboService;

    @AuthIgnore
    @PostMapping("/relation")
    @ApiOperation("V5.4.0--级联方式获取筛选条件(1.信用标 2.抵押标 3.转让区)")
    public Result<InvestOrderRelationResponseVO> getTradableInvestOrderRelationConfig(@RequestBody @Valid InvestOrderRelationRequestVO request) {
        InvestOrderRelationResponseVO result = new InvestOrderRelationResponseVO();

        TradableInvestOrderFilterRequestDTO requestDTO = new TradableInvestOrderFilterRequestDTO();
        InvestStdProductTypeEnum investStdProductTypeEnum = InvestStdProductTypeEnum.enumOf(request.getFiterType());
        requestDTO.setConfigType(request.getConfigType() == 0 || request.getConfigType() == 0 ? null : request.getConfigType());
        requestDTO.setLoanTypeConfigId(request.getLoanTypeConfigId());
        requestDTO.setPeriodConfigId(request.getRestPeriodConfigId());
        requestDTO.setRepaymentTypeConfigId(request.getRepaymentTypeConfigId());
        requestDTO.setInterestRateConfigId(request.getInterestRateConfigId());
        requestDTO.setProductType(investStdProductTypeEnum.getValue());

        List<RelationInvestStdConfigItemDTO> list = creditorConfigDubboService.getCreditorRelationQueryCondition(requestDTO);

        if (list == null || list.isEmpty()) return Result.with(new InvestOrderRelationResponseVO());

        List<ConfigItem> productType = new ArrayList<>();
        List<ConfigVO> restPeriod = new ArrayList<>();
        List<ConfigItem> repaymentType = new ArrayList<>();
        List<ConfigVO> interestReate = new ArrayList<>();
        List<ConfigVO> investableAmount = new ArrayList<>();
        for (RelationInvestStdConfigItemDTO item : list) {
            switch (item.getConfigType()) { //参见 InvestStdConfigTypeEnum
                case 1: //标的类型
                    productType.add(new ConfigItem(item.getId(), String.valueOf(item.getByteVal()), item.getTitle()));
                    break;
                case 2: //剩余期限
                    restPeriod.add(getConfigVO(item));
                    break;
                case 3: //还款方式
                    repaymentType.add(new ConfigItem(item.getId(), String.valueOf(item.getByteVal()), item.getTitle()));
                    break;
                case 4: //利率
                    interestReate.add(getConfigVO(item));
                    break;
                case 5: //可投金额
                    investableAmount.add(getConfigVO(item));
                    break;
            }
        }

        result.setInterestReate(interestReate);
        result.setProductType(productType);
        result.setRepaymentType(repaymentType);
        result.setRestPeriod(restPeriod);
        result.setInvestableAmount(investableAmount);
        return Result.with(result);
    }

    private ConfigVO getConfigVO(RelationInvestStdConfigItemDTO item) {
        ConfigVO configArea = new ConfigVO();
        configArea.setConfigId(item.getId());
        configArea.setTitle(item.getTitle());
        FilterInvestConfigDTO.Config config = new FilterInvestConfigDTO.Config();
        config.setMinvalCalSymbol(item.getMinvalCalSymbol());
        config.setMinval(item.getMinval());
        config.setMaxvalCalSymbol(item.getMaxvalCalSymbol());
        config.setMaxval(item.getMaxval());
        config.setTermUnit(item.getTermUnit());
        configArea.setValue(config);
        return configArea;
    }

}
